/* 
Scenic Graphics Library
Copyright (C) 2007 Jouni Tulkki

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USApackage scenic;
*/

package scenic.jni;

import java.awt.Rectangle;
import java.awt.geom.AffineTransform;

import scenic.SceneSettings;
import scenic.Color;
import scenic.filter.Filter;
import scenic.filter.Kernel;

public class Renderer {
	static {
		scenic.jni.RenderCanvas.loadLibrary();
	}
	
	private static Thread renderingThread;
	
	public static final int SURFACE_TYPE_COLOR = 0;
	public static final int SURFACE_TYPE_ALPHA = 1;
	public static final int SURFACE_TYPE_ALPHA2X = 2;
	public static final int SURFACE_TYPE_ALPHA4X = 3;
	
	public native void nativeEnterCriticalSection();
	public native void nativeLeaveCriticalSection();
		
	public void enterCriticalSection() {
		nativeEnterCriticalSection();
		renderingThread = Thread.currentThread();
	}
	
	public void leaveCriticalSection() {
		renderingThread = null;
		nativeLeaveCriticalSection();
	}
	
	public static Thread getRenderingThread() {
		return renderingThread;
	}
	
	public int createContextForCanvas(RenderCanvas canvas) {
		return createContextForCanvas(canvas.id);
	}
	
	public native int createContextForCanvas(int canvas);
	public native int createContextForImage(int image);
	public native void deleteContext(int context);
	
	public native boolean beginScene(int context);
	public native void endScene(int context);
	public native void present(int context);
	
	// Options
	private native void setPolygonAntialias(int context, boolean value);
	private native void setPolygonAntialiasingFilter(int context, Kernel filter, double width, double height);
	public void setPolygonAntialiasingFilter(int context, Filter filter) {
		if(filter == null)
			setPolygonAntialias(context, false);
		else if(filter == SceneSettings.getDefaultAAFilter())
			setPolygonAntialias(context, true);
		else
			setPolygonAntialiasingFilter(context, filter.getKernel(), filter.getWidth(), filter.getHeight());
	}	
	public native void setTransform(int context, double m00, double m01, 
			double m10, double m11, double dx, double dy);
	public void setTransform(int context, AffineTransform t) {
		setTransform(context, t.getScaleX(), t.getShearX(), 
				t.getShearY(), t.getScaleY(), t.getTranslateX(), t.getTranslateY());
	}
	public native void setColorSpace(int context, boolean isLinear);

	// Drawing
	public native void color(int context, float r, float g, float b, float a);
	public void color(int context, Color c) {
		color(context, c.red, c.green, c.blue, c.alpha);
	}
	public native void clear(int context);
	public native void drawImage(int context, int image, double x, double y, 
			double width, double height);
	public native void solidColor(int context);
	
	public native void gradient(int context, int type, int cycleMethod, int image);

	// Text
	public native void beginText(int context);
	public native void endText(int context);
	public native void setTextTexture(int context, int image);
	public native void drawGlyph(int context, float tex_x, float tex_y, 
			float tex_width, float tex_height, int screen_x, int screen_y,
			int screen_widtht, int screen_height);
	
	// Tesselerator
	public native void tessBegin(int context);
	public native void tessEnd(int context);
/*	public native void tessBeginContour(int context);
	public native void tessEndContour(int context); */
	public native void tessVertex(int context, double x, double y);
	public native void tessTriangle(int context, int vertex1, boolean edge1, int vertex2, boolean edge2,
			int vertex3, boolean edge3);
	
	// Line
	public native void polylineSetStyle(int context, float width, int cap, int joint, float miterLimit,
			float[] lineDashLengths, double lineDashPhase);
	public native void polylineBegin(int context, boolean closed);
	public native void polylineEnd(int context);
	public native void polylinePoint(int context, double x, double y);
	
	// Primitives
	public native void beginPrimitives(int context);
	public native void setAttribute(int context, int index, int size, byte[] data);
	public native void setAttribute(int context, int index, int size, float[] data);
	public native void setFragmentParameter(int context, int index, float[] parameter);
	public native void setTexture(int context, int index, int image);
	public native void drawIndices(int context, int type, int[] indices);
	public native void endPrimitives(int context);
	
	// Surfaces
	public native int beginClip(int context, int x, int y, int width, int height);
	public boolean beginClip(int context, Rectangle bounds) {
		return beginClip(context, bounds.x, bounds.y, bounds.width, bounds.height) != 0;
	}
	public native int beginSurface(int context, int x, int y, int width, int height, int type);
	public int beginSurface(int context, Rectangle bounds, int type) {
		return beginSurface(context, bounds.x, bounds.y, bounds.width, bounds.height, type);
	}
	public native void drawSurface(int context);
	public native void drawSurfaceAndClip(int context);
	public native void discardSurface(int context);
}
